package com.shopnight.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shopnight.dto.WXAuthDto;
import com.shopnight.dto.WxPhoneInfoDto;
import com.shopnight.entity.Rider;
import com.shopnight.entity.ShopAdmin;
import com.shopnight.entity.User;
import com.shopnight.interceptors.JWTInterceptor;
import com.shopnight.mapper.RiderMapper;
import com.shopnight.mapper.ShopAdminMapper;
import com.shopnight.mapper.ShopIndentMapper;
import com.shopnight.result.ApiResult;
import com.shopnight.service.UserService;
import com.shopnight.mapper.UserMapper;
import com.shopnight.utils.UserContext;
import com.shopnight.utils.jwtUtils;
import com.shopnight.vo.UserInfo;
import com.shopnight.vo.UserRankedVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.spec.AlgorithmParameterSpec;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


/**
* @author 86155
* @description 针对表【user(用户信息表)】的数据库操作Service实现
* @createDate 2022-08-31 17:16:38
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService {

    @Value("${wx.mini.appid}")
    private String appid;
    @Value("${wx.mini.secret}")
    private String secret;

    private String prefix = "wx_session_id_";

    @Autowired
    UserMapper userMapper;

    @Autowired
    ShopIndentMapper shopIndentMapper;

    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RiderMapper riderMapper;
    @Autowired
    ShopAdminMapper shopAdminMapper;


    public ApiResult<Object> login(Map<String,Object> verify) {

        String phone = verify.get("phone").toString() ;
//        String code = verify.get("code").toString() ;

        if(phone.length() != 11){
            return ApiResult.fail("手机号为11位");
        }else {
            String regex = "^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\\d{8}$";
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(phone);

            if(! m.matches() ){
                return ApiResult.fail("手机号错误!");
            }
        }

//        if ( code.equals(  phone.substring(phone.length() - 4) ) ){

            if (verify.containsKey("captcha")){
                String loginCaptcha = verify.get("captcha").toString() ;
                //K 验证码:userID:goodsID   V 验证码值
                String  redisLoginCaptcha= (String) stringRedisTemplate.opsForValue().get("loginCaptcha:"+ phone);
                if (!loginCaptcha.equals(redisLoginCaptcha)){
                    return ApiResult.fail("图像值错误");
                }
            }else
                return   ApiResult.fail("请输入图像验证码！");

            User user = userMapper.selectOne(
                    new LambdaQueryWrapper<User>().eq(User::getPhonenumber, phone)
            );
            if (user != null){
                Map<String,Object> mapUserId =  new HashMap<>();
                mapUserId.put("userId",user.getUserId());
                String token =  jwtUtils.getToken( mapUserId);
                return  ApiResult.ok("登陆成功!","token");

            }else{
                User user2 = new User();
                user2.setPhonenumber( phone );
                user2.setUserType(1);
                user2.setCreateTime(new Date());
                user2.setStatus(1);
                userMapper.insert(user2);
                Map<String,Object> mapUserId =  new HashMap<>();
                mapUserId.put("userId",user2.getUserId());
                String token = jwtUtils.getToken( JSONObject.parseObject(JSON.toJSONString( mapUserId )) );
                return  ApiResult.ok("登陆成功!","token");
            }

    }


    //获取验证码
//    @Override
//    public ApiResult<Object> getPhoneVerifyCode(Map<String, Object> phone) throws ClientException {
//
//        CodeVO codeVO = JSON.parseObject(
//                (String) stringRedisTemplate.opsForHash().get("phone",phone.get("phone")),
//                CodeVO.class
//        ) ;
//
//        if (codeVO != null) {
//            if ((new Date().getTime() - Long.valueOf(codeVO.getCodeExpiration())) < 1000 * 60 ) {
//                return ApiResult.fail("一分钟内请勿重复发送！");
//            }
//        }
//
//            String randomNum = createRandomNum(4);
//            String templateParam = "{\"code\": \"" + randomNum + "\"}";//转义字符\"
//            Map<String, String> paramMap = new HashMap<>();
//            paramMap.put("phoneNumber", phone.get("phone").toString());//接收者的手机号
//            paramMap.put("templateParam", templateParam);
//            SendSmsResponse sendSmsResponse = null;
//            sendSmsResponse = SmsAliyun.sendSms(paramMap);
//            if (!(sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK"))) {
//                if (sendSmsResponse.getCode() == null) {
//                    return ApiResult.fail("请wx联系:15555881410");
//                }
//                if (!sendSmsResponse.getCode().equals("错误")) {
//                    return ApiResult.fail("请wx联系:15555881410");
//                }
//            }
//
//           String phontString = phone.get("phone").toString();
//
//            CodeVO codeVO2 = new CodeVO();
//            codeVO2.setCode(randomNum);
//            codeVO2.setCodeExpiration(String.valueOf(new Date().getTime()));
//
//        //存入key到redis
//        stringRedisTemplate.opsForHash().put("phone", phontString, JSON.toJSONString(codeVO2) );
//        return ApiResult.ok("发送成功");
//        }



    @Override
    public ApiResult<Object> getUserByToken() {
        String userId = UserContext.getEndUserId();
        User user = userMapper.selectById(userId);
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(user,userInfo);

        Rider rider = riderMapper.selectOne(
                new LambdaQueryWrapper<Rider>()
                        .eq(Rider::getUserId, userId)
                        .eq(Rider::getState,1)
        );
        if (userInfo.getAdminId() != null){

//            List<Long> adminIdList = Arrays.stream(userInfo.getAdminId().split(","))
//                    .map(String::trim)
//                    .map(Long::valueOf)
//                    .collect(Collectors.toList());
//            ShopAdmin shopAdmin = shopAdminMapper.selectById(adminIdList.get(0));
//            userInfo.setAdminName(shopAdmin.getAdminName());
            userInfo.setAdminName("开始配送");
        }

        if (rider != null){
            userInfo.setIsRider(1 );
        }else  userInfo.setIsRider(0);

        return ApiResult.ok( userInfo );
    }

  /* 获取用户消费排名*/
    @Override
    public List<UserRankedVO>  getUserRanked() {
        return  userMapper.getUserRanked();
    }

    @Override
    public Map<String,String> getSessionId(String code) {
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code";
        String replaceUrl = url.replace("{0}",appid)
                               .replace("{1}",secret)
                               .replace("{2}",code);
        String res = HttpUtil.get(replaceUrl);
        String uuid = UUID.randomUUID().toString();
        stringRedisTemplate.opsForValue().set(prefix + uuid,res,30, TimeUnit.MINUTES);
        Map<String,String> map = new HashMap<>();
        map.put("sessionId",uuid);
        return map;
    }

    @Override
    public String authLogin(WXAuthDto wxAuthDto) {
        //1.通过wxauth的值 要对他进行解密
        try {
            //读取session数据
            String json = stringRedisTemplate.opsForValue().get(prefix + wxAuthDto.getSessionId());
            JSONObject jsonObject = JSON.parseObject(json);
            String sessionKey = (String) jsonObject.get("session_key");
            String openId = (String) jsonObject.get("openid");

            Long tokenUserId ;
            //检查数据库有没有唯一的opneid值
            User userByOpenid = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getOpenId, openId));

            if (userByOpenid == null){
                //查询有无此手机号用户  解密
                String s = wxDecrypt(wxAuthDto.getEncryptedData(), sessionKey, wxAuthDto.getIv());
                WxPhoneInfoDto wxPhoneInfoDto = JSON.parseObject(s, WxPhoneInfoDto.class);
                //用户手机号
                String phoneNumber = wxPhoneInfoDto.getPhoneNumber();
                User userByPhonenumber = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getPhonenumber, phoneNumber));
                //此用户为h5时注册用户
                if (userByPhonenumber != null){
                    //加入唯一标识符openid
                    userByPhonenumber.setOpenId(openId);
                    //如果没有昵称
                    if(userByPhonenumber.getUserNick() == null){
                        userByPhonenumber.setUserNick("用户" + phoneNumber.substring(phoneNumber.length()-4) );
                    }
                    //如果没有头像
                    if(userByPhonenumber.getAvatar() == null){
                        userByPhonenumber.setAvatar("https://ejxy.oss-cn-hangzhou.aliyuncs.com/user/2023-06-26/1687714897140.jpg");
                    }
                    userMapper.updateById(userByPhonenumber);
                    tokenUserId = userByPhonenumber.getUserId();
                }else {
                 //此用户为新注册用户
                    User user = new User();
                    user.setOpenId(openId);
                    user.setUserType(2);   //2-》 微信一键注册
                    user.setPhonenumber(phoneNumber);
                    //设置用户 默认头像 已经昵称
                    user.setUserNick("用户" + phoneNumber.substring(phoneNumber.length()-4) );
                    user.setAvatar("https://ejxy.oss-cn-hangzhou.aliyuncs.com/user/2023-06-26/1687714897140.jpg");
                    user.setStatus(1);
                    user.setLoginDate(new Date());
                    user.setCreateTime(new Date());
                    userMapper.insert(user);  //插入数据库注册用户
                    tokenUserId = user.getUserId();
                }


            }else {
                tokenUserId = userByOpenid.getUserId();
            }
            Map<String,Object> mapUserId =  new HashMap<>();
            mapUserId.put("userId",tokenUserId);

            return jwtUtils.getToken( mapUserId);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }


    }


    public String wxDecrypt(String encryptData,String sessionKey,String vi) throws Exception {
        byte[] encData = cn.hutool.core.codec.Base64.decode(encryptData);
        byte[] iv =  cn.hutool.core.codec.Base64.decode(vi);
        byte[] key = Base64.decode(sessionKey);
        AlgorithmParameterSpec ivSpec = new IvParameterSpec(iv);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(key,"AES");
        cipher.init(Cipher.DECRYPT_MODE,keySpec,ivSpec);
        return new String(cipher.doFinal(encData),"UTF-8");
    }


    @Override
    public User selectById(Integer userId) {
        User user = this.baseMapper.selectById(userId);
        return user;
    }

}




